use crate::src::src::compare_int::int_equal;
use crate::src::src::compare_string::string_equal;
use crate::src::src::hash_int::int_hash;
use crate::src::src::hash_string::string_hash;
use crate::src::src::hash_table::{
    hash_table_free, hash_table_insert, hash_table_iter_has_more, hash_table_iter_next,
    hash_table_iterate, hash_table_lookup, hash_table_new, hash_table_num_entries,
    hash_table_register_free_functions, hash_table_remove,
};
use crate::src::struct_and_type::{
    HashTable, HashTableEntry, HashTableIterator, HashTableKey, HashTablePair, HashTableValue,
    UnitTestFunction,
};
use crate::src::test::alloc_testing::{
    alloc_test_free, alloc_test_get_allocated, alloc_test_malloc, alloc_test_set_limit,
    alloc_test_strdup,
};
use crate::src::test::framework::run_tests;
use :: libc;
extern "C" {
    fn sprintf(_: *mut i8, _: *const i8, _: ...) -> i32;
    fn atoi(__nptr: *const i8) -> i32;
    fn strcmp(_: *const i8, _: *const i8) -> i32;
}
#[no_mangle]
pub static mut value1: i32 = 1 as i32;
#[no_mangle]
pub static mut value2: i32 = 2 as i32;
#[no_mangle]
pub static mut value3: i32 = 3 as i32;
#[no_mangle]
pub static mut value4: i32 = 4 as i32;
#[no_mangle]
pub static mut allocated_keys: i32 = 0 as i32;
#[no_mangle]
pub static mut allocated_values_test_hash_table: i32 = 0 as i32;
#[no_mangle]
pub extern "C" fn generate_hash_table() -> *mut HashTable {
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    let mut buf: [i8; 10] = [0; 10];
    let mut value: *mut i8 = 0 as *mut i8;
    let mut i: i32 = 0;
    hash_table = hash_table_new(
        Some(string_hash as unsafe extern "C" fn(*mut libc::c_void) -> u32),
        Some(string_equal as unsafe extern "C" fn(*mut libc::c_void, *mut libc::c_void) -> i32),
    );
    i = 0 as i32;
    while i < 10000 as i32 {
        (unsafe { sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const i8, i) });
        value = alloc_test_strdup(buf.as_mut_ptr());
        hash_table_insert(hash_table, value as HashTableKey, value as HashTableValue);
        i += 1;
        i;
    }
    hash_table_register_free_functions(
        hash_table,
        None,
        Some(alloc_test_free as unsafe extern "C" fn(*mut libc::c_void) -> ()),
    );
    return hash_table;
}
#[no_mangle]
pub extern "C" fn test_hash_table_new_free() {
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    hash_table = hash_table_new(
        Some(int_hash as unsafe extern "C" fn(*mut libc::c_void) -> u32),
        Some(int_equal as unsafe extern "C" fn(*mut libc::c_void, *mut libc::c_void) -> i32),
    );
    assert!(!hash_table.is_null());
    hash_table_insert(
        hash_table,
        (unsafe { &mut value1 }) as *mut i32 as HashTableKey,
        (unsafe { &mut value1 }) as *mut i32 as HashTableValue,
    );
    hash_table_insert(
        hash_table,
        (unsafe { &mut value2 }) as *mut i32 as HashTableKey,
        (unsafe { &mut value2 }) as *mut i32 as HashTableValue,
    );
    hash_table_insert(
        hash_table,
        (unsafe { &mut value3 }) as *mut i32 as HashTableKey,
        (unsafe { &mut value3 }) as *mut i32 as HashTableValue,
    );
    hash_table_insert(
        hash_table,
        (unsafe { &mut value4 }) as *mut i32 as HashTableKey,
        (unsafe { &mut value4 }) as *mut i32 as HashTableValue,
    );
    hash_table_free(hash_table);
    alloc_test_set_limit(0 as i32);
    hash_table = hash_table_new(
        Some(int_hash as unsafe extern "C" fn(*mut libc::c_void) -> u32),
        Some(int_equal as unsafe extern "C" fn(*mut libc::c_void, *mut libc::c_void) -> i32),
    );
    assert!(hash_table.is_null());
    assert!(alloc_test_get_allocated() == 0 as i32 as u64);
    alloc_test_set_limit(1 as i32);
    hash_table = hash_table_new(
        Some(int_hash as unsafe extern "C" fn(*mut libc::c_void) -> u32),
        Some(int_equal as unsafe extern "C" fn(*mut libc::c_void, *mut libc::c_void) -> i32),
    );
    assert!(hash_table.is_null());
    assert!(alloc_test_get_allocated() == 0 as i32 as u64);
}
#[no_mangle]
pub extern "C" fn test_hash_table_insert_lookup() {
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    let mut buf: [i8; 10] = [0; 10];
    let mut value: *mut i8 = 0 as *mut i8;
    let mut i: i32 = 0;
    hash_table = generate_hash_table();
    assert!(hash_table_num_entries(hash_table) == 10000 as i32 as u32);
    i = 0 as i32;
    while i < 10000 as i32 {
        (unsafe { sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const i8, i) });
        value = hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey) as *mut i8;
        assert!((unsafe { strcmp(value, buf.as_mut_ptr()) }) == 0 as i32);
        i += 1;
        i;
    }
    (unsafe {
        sprintf(
            buf.as_mut_ptr(),
            b"%i\0" as *const u8 as *const i8,
            -(1 as i32),
        )
    });
    assert!((hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey)).is_null());
    (unsafe {
        sprintf(
            buf.as_mut_ptr(),
            b"%i\0" as *const u8 as *const i8,
            10000 as i32,
        )
    });
    assert!((hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey)).is_null());
    (unsafe {
        sprintf(
            buf.as_mut_ptr(),
            b"%i\0" as *const u8 as *const i8,
            12345 as i32,
        )
    });
    hash_table_insert(
        hash_table,
        buf.as_mut_ptr() as HashTableKey,
        alloc_test_strdup(b"hello world\0" as *const u8 as *const i8) as HashTableValue,
    );
    value = hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey) as *mut i8;
    assert!((unsafe { strcmp(value, b"hello world\0" as *const u8 as *const i8) }) == 0 as i32);
    hash_table_free(hash_table);
}
#[no_mangle]
pub extern "C" fn test_hash_table_remove() {
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    let mut buf: [i8; 10] = [0; 10];
    hash_table = generate_hash_table();
    assert!(hash_table_num_entries(hash_table) == 10000 as i32 as u32);
    (unsafe {
        sprintf(
            buf.as_mut_ptr(),
            b"%i\0" as *const u8 as *const i8,
            5000 as i32,
        )
    });
    assert!(!(hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey)).is_null());
    hash_table_remove(hash_table, buf.as_mut_ptr() as HashTableKey);
    assert!(hash_table_num_entries(hash_table) == 9999 as i32 as u32);
    assert!((hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey)).is_null());
    (unsafe {
        sprintf(
            buf.as_mut_ptr(),
            b"%i\0" as *const u8 as *const i8,
            -(1 as i32),
        )
    });
    hash_table_remove(hash_table, buf.as_mut_ptr() as HashTableKey);
    assert!(hash_table_num_entries(hash_table) == 9999 as i32 as u32);
    hash_table_free(hash_table);
}
#[no_mangle]
pub extern "C" fn test_hash_table_iterating() {
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    let mut iterator: HashTableIterator = HashTableIterator {
        hash_table: 0 as *mut HashTable,
        next_entry: 0 as *mut HashTableEntry,
        next_chain: 0,
    };
    let mut count: i32 = 0;
    hash_table = generate_hash_table();
    count = 0 as i32;
    hash_table_iterate(hash_table, &mut iterator);
    while hash_table_iter_has_more(&mut iterator) != 0 {
        hash_table_iter_next(&mut iterator);
        count += 1;
        count;
    }
    assert!(count == 10000 as i32);
    let mut pair: HashTablePair = hash_table_iter_next(&mut iterator);
    assert!((pair.value).is_null());
    hash_table_free(hash_table);
    hash_table = hash_table_new(
        Some(int_hash as unsafe extern "C" fn(*mut libc::c_void) -> u32),
        Some(int_equal as unsafe extern "C" fn(*mut libc::c_void, *mut libc::c_void) -> i32),
    );
    hash_table_iterate(hash_table, &mut iterator);
    assert!(hash_table_iter_has_more(&mut iterator) == 0 as i32);
    hash_table_free(hash_table);
}
#[no_mangle]
pub extern "C" fn test_hash_table_iterating_remove() {
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    let mut iterator: HashTableIterator = HashTableIterator {
        hash_table: 0 as *mut HashTable,
        next_entry: 0 as *mut HashTableEntry,
        next_chain: 0,
    };
    let mut buf: [i8; 10] = [0; 10];
    let mut val: *mut i8 = 0 as *mut i8;
    let mut pair: HashTablePair = HashTablePair {
        key: 0 as *mut libc::c_void,
        value: 0 as *mut libc::c_void,
    };
    let mut count: i32 = 0;
    let mut removed: u32 = 0;
    let mut i: i32 = 0;
    hash_table = generate_hash_table();
    count = 0 as i32;
    removed = 0 as i32 as u32;
    hash_table_iterate(hash_table, &mut iterator);
    while hash_table_iter_has_more(&mut iterator) != 0 {
        pair = hash_table_iter_next(&mut iterator);
        val = pair.value as *mut i8;
        if (unsafe { atoi(val) }) % 100 as i32 == 0 as i32 {
            hash_table_remove(hash_table, val as HashTableKey);
            removed = removed.wrapping_add(1);
            removed;
        }
        count += 1;
        count;
    }
    assert!(removed == 100 as i32 as u32);
    assert!(count == 10000 as i32);
    assert!(hash_table_num_entries(hash_table) == (10000 as i32 as u32).wrapping_sub(removed));
    i = 0 as i32;
    while i < 10000 as i32 {
        (unsafe { sprintf(buf.as_mut_ptr(), b"%i\0" as *const u8 as *const i8, i) });
        if i % 100 as i32 == 0 as i32 {
            assert!((hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey)).is_null());
        } else {
            assert!(!(hash_table_lookup(hash_table, buf.as_mut_ptr() as HashTableKey)).is_null());
        }
        i += 1;
        i;
    }
    hash_table_free(hash_table);
}
#[no_mangle]
pub extern "C" fn new_key(mut value: i32) -> *mut i32 {
    let mut result: *mut i32 = 0 as *mut i32;
    result = alloc_test_malloc(::core::mem::size_of::<i32>() as u64) as *mut i32;
    (unsafe { *result = value });
    (unsafe { allocated_keys += 1 });
    (unsafe { allocated_keys });
    return result;
}
#[no_mangle]
pub extern "C" fn free_key(mut key: *mut libc::c_void) {
    alloc_test_free(key);
    (unsafe { allocated_keys -= 1 });
    (unsafe { allocated_keys });
}
#[no_mangle]
pub extern "C" fn new_value_test_hash_table(mut value: i32) -> *mut i32 {
    let mut result: *mut i32 = 0 as *mut i32;
    result = alloc_test_malloc(::core::mem::size_of::<i32>() as u64) as *mut i32;
    (unsafe { *result = value });
    (unsafe { allocated_values_test_hash_table += 1 });
    (unsafe { allocated_values_test_hash_table });
    return result;
}
#[no_mangle]
pub extern "C" fn free_value_test_hash_table(mut value: *mut libc::c_void) {
    alloc_test_free(value);
    (unsafe { allocated_values_test_hash_table -= 1 });
    (unsafe { allocated_values_test_hash_table });
}
#[no_mangle]
pub extern "C" fn test_hash_table_free_functions() {
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    let mut key: *mut i32 = 0 as *mut i32;
    let mut value: *mut i32 = 0 as *mut i32;
    let mut i: i32 = 0;
    hash_table = hash_table_new(
        Some(int_hash as unsafe extern "C" fn(*mut libc::c_void) -> u32),
        Some(int_equal as unsafe extern "C" fn(*mut libc::c_void, *mut libc::c_void) -> i32),
    );
    hash_table_register_free_functions(
        hash_table,
        Some(free_key as unsafe extern "C" fn(*mut libc::c_void) -> ()),
        Some(free_value_test_hash_table as unsafe extern "C" fn(*mut libc::c_void) -> ()),
    );
    (unsafe { allocated_values_test_hash_table = 0 as i32 });
    i = 0 as i32;
    while i < 10000 as i32 {
        key = new_key(i);
        value = new_value_test_hash_table(99 as i32);
        hash_table_insert(hash_table, key as HashTableKey, value as HashTableValue);
        i += 1;
        i;
    }
    assert!((unsafe { allocated_keys }) == 10000 as i32);
    assert!((unsafe { allocated_values_test_hash_table }) == 10000 as i32);
    i = 10000 as i32 / 2 as i32;
    hash_table_remove(hash_table, &mut i as *mut i32 as HashTableKey);
    assert!((unsafe { allocated_keys }) == 10000 as i32 - 1 as i32);
    assert!((unsafe { allocated_values_test_hash_table }) == 10000 as i32 - 1 as i32);
    key = new_key(10000 as i32 / 3 as i32);
    value = new_value_test_hash_table(999 as i32);
    assert!((unsafe { allocated_keys }) == 10000 as i32);
    assert!((unsafe { allocated_values_test_hash_table }) == 10000 as i32);
    hash_table_insert(hash_table, key as HashTableKey, value as HashTableValue);
    assert!((unsafe { allocated_keys }) == 10000 as i32 - 1 as i32);
    assert!((unsafe { allocated_values_test_hash_table }) == 10000 as i32 - 1 as i32);
    hash_table_free(hash_table);
    assert!((unsafe { allocated_keys }) == 0 as i32);
    assert!((unsafe { allocated_values_test_hash_table }) == 0 as i32);
}
#[no_mangle]
pub extern "C" fn test_hash_table_out_of_memory() {
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    let mut values: [i32; 66] = [0; 66];
    let mut i: u32 = 0;
    hash_table = hash_table_new(
        Some(int_hash as unsafe extern "C" fn(*mut libc::c_void) -> u32),
        Some(int_equal as unsafe extern "C" fn(*mut libc::c_void, *mut libc::c_void) -> i32),
    );
    alloc_test_set_limit(0 as i32);
    values[0 as i32 as usize] = 0 as i32;
    assert!(
        hash_table_insert(
            hash_table,
            (unsafe { &mut *values.as_mut_ptr().offset(0 as i32 as isize) }) as *mut i32
                as HashTableKey,
            (unsafe { &mut *values.as_mut_ptr().offset(0 as i32 as isize) }) as *mut i32
                as HashTableValue,
        ) == 0 as i32
    );
    assert!(hash_table_num_entries(hash_table) == 0 as i32 as u32);
    alloc_test_set_limit(-(1 as i32));
    i = 0 as i32 as u32;
    while i < 65 as i32 as u32 {
        values[i as usize] = i as i32;
        assert!(
            hash_table_insert(
                hash_table,
                (unsafe { &mut *values.as_mut_ptr().offset(i as isize) }) as *mut i32
                    as HashTableKey,
                (unsafe { &mut *values.as_mut_ptr().offset(i as isize) }) as *mut i32
                    as HashTableValue,
            ) != 0 as i32
        );
        assert!(hash_table_num_entries(hash_table) == i.wrapping_add(1 as i32 as u32));
        i = i.wrapping_add(1);
        i;
    }
    assert!(hash_table_num_entries(hash_table) == 65 as i32 as u32);
    alloc_test_set_limit(0 as i32);
    values[65 as i32 as usize] = 65 as i32;
    assert!(
        hash_table_insert(
            hash_table,
            (unsafe { &mut *values.as_mut_ptr().offset(65 as i32 as isize) }) as *mut i32
                as HashTableKey,
            (unsafe { &mut *values.as_mut_ptr().offset(65 as i32 as isize) }) as *mut i32
                as HashTableValue,
        ) == 0 as i32
    );
    assert!(hash_table_num_entries(hash_table) == 65 as i32 as u32);
    hash_table_free(hash_table);
}
#[no_mangle]
pub extern "C" fn test_hash_iterator_key_pair() {
    let mut hash_table: *mut HashTable = 0 as *mut HashTable;
    let mut iterator: HashTableIterator = HashTableIterator {
        hash_table: 0 as *mut HashTable,
        next_entry: 0 as *mut HashTableEntry,
        next_chain: 0,
    };
    let mut pair: HashTablePair = HashTablePair {
        key: 0 as *mut libc::c_void,
        value: 0 as *mut libc::c_void,
    };
    hash_table = hash_table_new(
        Some(int_hash as unsafe extern "C" fn(*mut libc::c_void) -> u32),
        Some(int_equal as unsafe extern "C" fn(*mut libc::c_void, *mut libc::c_void) -> i32),
    );
    hash_table_insert(
        hash_table,
        (unsafe { &mut value1 }) as *mut i32 as HashTableKey,
        (unsafe { &mut value1 }) as *mut i32 as HashTableValue,
    );
    hash_table_insert(
        hash_table,
        (unsafe { &mut value2 }) as *mut i32 as HashTableKey,
        (unsafe { &mut value2 }) as *mut i32 as HashTableValue,
    );
    hash_table_iterate(hash_table, &mut iterator);
    while hash_table_iter_has_more(&mut iterator) != 0 {
        pair = hash_table_iter_next(&mut iterator);
        let mut key: *mut i32 = pair.key as *mut i32;
        let mut val: *mut i32 = pair.value as *mut i32;
        assert!((unsafe { *key }) == (unsafe { *val }));
    }
    hash_table_free(hash_table);
}
static mut tests_test_hash_table: [UnitTestFunction; 9] = unsafe {
    [
        Some(test_hash_table_new_free as unsafe extern "C" fn() -> ()),
        Some(test_hash_table_insert_lookup as unsafe extern "C" fn() -> ()),
        Some(test_hash_table_remove as unsafe extern "C" fn() -> ()),
        Some(test_hash_table_iterating as unsafe extern "C" fn() -> ()),
        Some(test_hash_table_iterating_remove as unsafe extern "C" fn() -> ()),
        Some(test_hash_table_free_functions as unsafe extern "C" fn() -> ()),
        Some(test_hash_table_out_of_memory as unsafe extern "C" fn() -> ()),
        ::core::mem::transmute::<Option<unsafe extern "C" fn() -> ()>, UnitTestFunction>(Some(
            ::core::mem::transmute::<unsafe extern "C" fn() -> (), unsafe extern "C" fn() -> ()>(
                test_hash_iterator_key_pair,
            ),
        )),
        None,
    ]
};
fn main_0_test_hash_table(mut _argc: i32, mut _argv: *mut *mut i8) -> i32 {
    run_tests(unsafe { tests_test_hash_table.as_mut_ptr() });
    return 0 as i32;
}
pub fn main_test_hash_table() {
    let mut args: Vec<*mut i8> = Vec::new();
    for arg in ::std::env::args() {
        args.push(
            (::std::ffi::CString::new(arg))
                .expect("Failed to convert argument into CString.")
                .into_raw(),
        );
    }
    args.push(::core::ptr::null_mut());
    {
        ::std::process::exit(main_0_test_hash_table(
            (args.len() - 1) as i32,
            args.as_mut_ptr() as *mut *mut i8,
        ) as i32)
    }
}
